package cn.edu.zsc.rbac.view;

import cn.edu.zsc.rbac.domain.dto.RoleDto;
import cn.edu.zsc.rbac.domain.enums.RoleDataScope;
import cn.edu.zsc.rbac.domain.vo.RoleVo;
import cn.edu.zsc.rbac.domain.vo.Result;
import cn.edu.zsc.rbac.service.IRoleService;
import cn.edu.zsc.rbac.service.impl.RoleService;
import cn.edu.zsc.rbac.util.DateTimeUtils;
import cn.edu.zsc.rbac.util.SingletonFactory;

public class RoleView extends BaseView<RoleVo, IRoleService>{
        public static final String MENU = """
                ———————————————————————
                        部门管理
                ———————————————————————
                 |     0...返回上级    |
                 |     1...角色列表    |
                 |     2...创建角色    |
                 |     3...更新角色    |
                 |     4...删除角色    |
                ———————————————————————
                请输入选项:""";
    private RoleView() {
        service =(RoleService) SingletonFactory.getInstance(RoleService.class);
    }
    public void show() {
        String menuChoice;
        do {
            System.out.print(MENU);
            menuChoice = MainView.input.nextLine();
            switch (menuChoice) {
                case "0" -> System.out.println("已返回上⼀级菜单");
                case "1" -> list();
                case "2" -> create();
                case "3" -> update();
                case "4" -> delete();
                default -> printError("输⼊⾮法，请输⼊正确的菜单编号！");
            }
        } while (!"0".equals(menuChoice));
    }
    /**
     * 列出所有角色的信息。
     * <p>
     * 本⽅法调⽤服务层获取所有角色数据，并将其存储在缓存中。然后，输出所有角色的 ID、名
     称和角色数据访问范围，
     * 以表格形式显示在控制台中，供⽤户查看。
     * </p>
     */
    public void list() {
        // 调⽤服务层获取所有角色数据
        Result result = service.list();
        // 将获取到的角色数据存⼊缓存
        cache = (RoleVo[]) result.data;
        // 输出表头
        System.out.println("ID\t角色名称\t角色角色数据访问范围\t更新时间");
        // 遍历缓存中的每个角色对象，输出角色的ID、名称和角色数据访问范围
        for (RoleVo role : cache) {
            if (role != null) {
                // 格式化输出每个角色的详细信息
                System.out.printf("%d\t%-5s\t%-10s\t%s\n", role.id, role.name,
                        role.dataScope, DateTimeUtils.format(role.updateAt));
            }
        }
    }
    /**
     * 创建⼀个新的角色。
     * <p>
     * 本⽅法会提示⽤户输⼊角色的名称和角色数据访问范围，并将这些信息封装到⼀个 `RoleDto` 对象中。
     * 然后调⽤服务层的创建⽅法，若创建成功，则输出成功信息并列出当前所有角色；若失败，则
     输出错误信息。
     * </p>
     */
    public void create() {
        // 提示⽤户输⼊角色名称
        System.out.print("请输⼊角色名称：");
        String name = MainView.input.nextLine(); // 获取⽤户输⼊的角色名称
        // 提示⽤户输⼊角色角色数据访问范围
        System.out.print("请输⼊角色角色数据访问范围，输入的值应该为【个人，部门，全局】其中之一：");
        //定义变量 dataScope，⽤于存储⽤户输⼊的合法数据访问范围
        RoleDataScope dataScope = null;
        // 使⽤ do - while 循环，持续获取⽤户输⼊，直⾄得到⼀个合法的值
        do {
            // 从控制台读取⽤户输⼊的字符串
            String str = MainView.input.nextLine();
            try {
                dataScope = Enum.valueOf(RoleDataScope.class, str);
            } catch (Exception e) {
                System.out.print("输⼊的值不合法，输⼊的值应该为 [个⼈、部⻔、全局] 其中之⼀，请重新输⼊：");
            }
        } while(dataScope == null);
        // 将⽤户输⼊的角色名称和角色数据访问范围封装到RoleDto对象中
        RoleDto dto = new RoleDto(name, dataScope);
        // 调⽤服务层的创建⽅法，创建新的角色
        Result result = service.create(dto);
        // 如果创建操作失败，输出错误信息
        if (!result.success) {
           printError(result.message);
            return; // 结束⽅法执⾏
        }
        // 创建成功，输出成功信息
        System.out.println(result.message);
        // 列出当前所有角色信息
        list();
    }
    /**
     * 更新指定角色的信息。
     * <p>
     * 本⽅法会提示⽤户输⼊角色的 ID，并验证该 ID 是否有效。然后从缓存中查找对应角色的数
     据，
     * 如果未找到角色，提示⽤户。如果找到角色，⽤户可以选择修改角色名称和角色数据访问范围，若⽤户没有
     修改，则保持原值。
     * 更新成功后，会返回更新结果并列出当前角色列表。
     * </p>
     */
    public void update() {
        // 在缓存中查找指定ID的角色，如果未找到角色，则返回
        RoleVo role = getCacheById();
        if (role == null) {
            return;
        }
        // 提示⽤户输⼊新的角色名称，按回⻋表示不修改
        System.out.print("请输⼊角色名称，直接按回⻋表示不修改：");
        String name = MainView.input.nextLine();
        // 如果⽤户没有输⼊新名称，保持原名称
        name = "".equals(name) ? role.name : name;
        // 提示⽤户输⼊新的角色角色数据访问范围，按回⻋表示不修改
        System.out.print("请输⼊角色角色数据访问范围，输⼊的值应该为 [个⼈、部⻔、全局] 其中之⼀，直接按回⻋表示不修改：");
        RoleDataScope dataScope = null;
        // 使⽤ do - while 循环，持续获取⽤户输⼊，直⾄得到⼀个合法的值
        do {
            // 获取⽤户输⼊的字符串
            String str = MainView.input.nextLine();
            // 如果⽤户输⼊的是空字符串（即直接按了回⻋），则保持数据访问范围为原⻆⾊的
            if ("".equals(str)) {
                // 如果没有输⼊内容，保持原有的访问范围不变
                dataScope = role.dataScope;
                break;
            }
            try {
                dataScope = Enum.valueOf(RoleDataScope.class, str);
            } catch (Exception e) {
                System.out.print("输⼊的值不合法，输⼊的值应该为 [个⼈、部⻔、全局] 其中之⼀，请重新输⼊：");
            }
        } while (dataScope == null);
        // 创建新的 RoleDto 对象，⽤于更新角色信息
        RoleDto dto = new RoleDto(name, dataScope);
        // 调⽤服务层更新角色信息
        Result result = service.update(dto, role.id);
        // 如果更新失败，显示错误信息
        if (!result.success) {
            printError(result.message);
            return;
        }
        // 更新成功，显示成功消息并列出角色信息
        System.out.println(result.message);
        list(); // 列出更新后的角色列表
    }
    /**
     * 删除指定角色信息。
     * <p>
     * 本⽅法会提示⽤户输⼊角色的 ID，并验证该 ID 是否有效。然后从缓存中查找对应角色数
     据，
     * 如果未找到角色，则提示⽤户。若找到角色，⽤户需确认是否删除该角色，确认后将删除该部
     ⻔。
     * 如果删除失败，则提示失败信息；删除成功后，重新列出角色信息。
     * </p>
     */
    public void delete() {
        RoleVo role = getCacheById();
        if (role == null) {
            return;
        }
        // 提示⽤户确认是否删除
        System.out.print("输⼊'Y'确认删除，输⼊其它取消删除：");
        String confirm = MainView.input.nextLine();
        // 如果⽤户输⼊的不是'Y'或'y'，则取消删除
        if (!"Y".equalsIgnoreCase(confirm)) {
            System.out.println("您已取消删除");
            return;
        }
        // 调⽤服务层进⾏删除操作
        Result result = service.delete(role.id);
        // 如果删除操作失败，提示错误信息
        if (!result.success) {
            printError(result.message);
            return;
        }
        // 删除成功，输出成功信息并列出当前角色列表
        System.out.println(result.message);
        list();
    }
}
